import { ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { AuthService } from "../auth/auth.service";

@Injectable()
export class JwtGuard extends AuthGuard("jwt") {
  constructor(private authService: AuthService) {
    super();
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    // 先执行父类的验证（验证 JWT 签名和过期时间）
    // 父类验证通过后，会将 JwtStrategy.validate() 返回的对象附加到 req.user
    const isValid = await super.canActivate(context);
    if (!isValid) {
      return false;
    }

    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);

    if (!token) {
      throw new UnauthorizedException("Token 不存在");
    }

    // 从 req.user 获取用户信息（由 JwtStrategy.validate() 设置）
    const userId = request.user?.userId;
    if (!userId) {
      throw new UnauthorizedException("用户信息无效");
    }

    try {
      // 验证 token 是否在 Redis 中存在
      const isTokenValid = await this.authService.validateToken(userId, token);
      if (!isTokenValid) {
        throw new UnauthorizedException("Token 已失效，请重新登录");
      }

      return true;
    } catch (error) {
      if (error instanceof UnauthorizedException) {
        throw error;
      }
      throw new UnauthorizedException("Token 验证失败");
    }
  }

  private extractTokenFromHeader(request: any): string | undefined {
    const [type, token] = request.headers.authorization?.split(" ") ?? [];
    return type === "Bearer" ? token : undefined;
  }
}
